//
//  RestConsumer.m
//  carritus
//
//  Created by Victor L. Fernandez Rodrigo on 06/10/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "RestConsumer.h"
#import "SBJson.h"
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "ASIDownloadCache.h"
#import "FinAppsNetwork.h"

#define kJSONFAKES YES

#define BASE_URI @"https://lacaixa.com/API/servihabitat/"

#define kNEARMEURL          @"habitats/nearme"
#define kSEARCHHOUSESURL    @"habitats/cercaFiltres"
#define kDETAILURL          @"habitat"
#define kTRACKINGURL        @"habitats/tracking"

#define TIMEOUT 15
#define kASIHTTPRequestTag				@"kASIHTTPRequestTag"
#define kASIHTTPResponseHanderDelegate	@"kASIHTTPDelegate"


@interface RestConsumer()

- (void)doRequest:(ASIHTTPRequest*)request 
          withTag:(NSString*)tag
      andDelegate:(id<DataFetchingHandler>)delegat;

- (void)makePostRequest:(NSString*)urlStr
           withPOSTData:(NSData*)data
                    tag:(NSString*)tag 
            andDelegate:(id<DataFetchingHandler>)delegat;

- (void)makeGetRequest:(NSString*)urlStr
			   withTag:(NSString*)tag
		   andDelegate:(id<DataFetchingHandler>)delegat;

- (id)parseStr:(NSString *)str;

@end



@implementation RestConsumer

#pragma mark -
#pragma mark public methods

- (void)getHousesNearLatitude:(float)latitude 
                 andLongitude:(float)longitude 
                   withRadius:(NSInteger)radius 
                         page:(NSInteger)page
             andNumberPerPage:(NSInteger)numPerPage 
                 withDelegate:(id<DataFetchingHandler>)delegate {
    
    NSString *urlStr = [[NSString alloc] initWithFormat:@"%@%@",BASE_URI,kNEARMEURL];
	NSLog(@"url: %@", urlStr);
    
    NSArray *keys = [[NSArray alloc] initWithObjects:@"latitude",@"longitude",@"radius",@"page",@"numPerPage",nil];
	NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:latitude],
                        [NSNumber numberWithFloat:longitude],
                        [NSNumber numberWithInt:radius],
                        [NSNumber numberWithInt:page],
                        [NSNumber numberWithInt:numPerPage],nil];
    
	NSDictionary *dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
	
	SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];
	NSString *strJSON = [jsonWriter stringWithObject:dict];
    
    NSLog(@"JSON: %@",strJSON);
    
    [self makePostRequest:urlStr
             withPOSTData:[strJSON dataUsingEncoding:NSUTF8StringEncoding] 
                      tag:kNEARMETAG
              andDelegate:delegate];
	
	[keys release];
	[objects release];
	[dict release];
	[jsonWriter release];
	[urlStr release];
    
}

- (void)searchHousesWithFiltersType:(float)searchType
                            inmoble:(NSString *)inmoble
                          provincia:(NSString *)provincia
                           poblacio:(NSString *)poblacio
                           segonaMa:(BOOL)segonaMa
                          aEstrenar:(BOOL)aEstrenar
                    nomesVacacional:(BOOL)nomesVacacional
                       withDelegate:(id<DataFetchingHandler>)delegate {
    
    NSString *urlStr = [[NSString alloc] initWithFormat:@"%@%@",BASE_URI,kSEARCHHOUSESURL];
	NSLog(@"url: %@", urlStr);
    
    NSArray *keys = [[NSArray alloc] initWithObjects:@"searchType",@"inmoble",@"provincia",@"poblacio",@"segonaMa",@"aEstrenar",@"nomesVacacional",nil];
	NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:searchType],
                        inmoble,
                        provincia,
                        poblacio,
                        [NSNumber numberWithBool:segonaMa],
                        [NSNumber numberWithBool:aEstrenar],
                        [NSNumber numberWithBool:nomesVacacional], nil];
    
	NSDictionary *dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
	
	SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];
	NSString *strJSON = [jsonWriter stringWithObject:dict];
    
    NSLog(@"JSON: %@",strJSON);
    
    [self makePostRequest:urlStr
             withPOSTData:[strJSON dataUsingEncoding:NSUTF8StringEncoding] 
                      tag:kSEARCHHOUSESTAG
              andDelegate:delegate];
	
	[keys release];
	[objects release];
	[dict release];
	[jsonWriter release];
	[urlStr release];
}

- (void)getDetailOfProductWithID:(NSInteger)pisID withDelegate:(id<DataFetchingHandler>)delegate {
    NSString *urlStr = [[NSString alloc] initWithFormat:@"%@%@",BASE_URI,kDETAILURL];
	NSLog(@"url: %@", urlStr);
    
    NSArray *keys = [[NSArray alloc] initWithObjects:@"flatID",nil];
	NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:pisID], nil];
    
	NSDictionary *dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
	
	SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];
	NSString *strJSON = [jsonWriter stringWithObject:dict];
    
    NSLog(@"JSON: %@",strJSON);
    
    [self makePostRequest:urlStr
             withPOSTData:[strJSON dataUsingEncoding:NSUTF8StringEncoding] 
                      tag:kDETAILTAG
              andDelegate:delegate];
	
	[keys release];
	[objects release];
	[dict release];
	[jsonWriter release];
	[urlStr release];
    
}


- (void)getTrackingNearLatitude:(float)latitude 
                   andLongitude:(float)longitude 
                     withRadius:(NSInteger)radius 
                   withDelegate:(id<DataFetchingHandler>)delegate {
    NSString *urlStr = [[NSString alloc] initWithFormat:@"%@%@",BASE_URI,kTRACKINGURL];
	NSLog(@"url: %@", urlStr);
    
    NSArray *keys = [[NSArray alloc] initWithObjects:@"latitude",@"longitude",@"radius",nil];
	NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:latitude],
                        [NSNumber numberWithFloat:longitude],
                        [NSNumber numberWithInt:radius],nil];
    
	NSDictionary *dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
	
	SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];
	NSString *strJSON = [jsonWriter stringWithObject:dict];
    
    NSLog(@"JSON: %@",strJSON);
    
    [self makePostRequest:urlStr
             withPOSTData:[strJSON dataUsingEncoding:NSUTF8StringEncoding] 
                      tag:kTRACKINGTAG
              andDelegate:delegate];
	
	[keys release];
	[objects release];
	[dict release];
	[jsonWriter release];
	[urlStr release];
}

#pragma mark -
#pragma mark private methods

-(NSUInteger)appDefaultCachePolicy{
	return ASIDoNotWriteToCacheCachePolicy|ASIDoNotReadFromCacheCachePolicy;
}

-(NSUInteger)appDefaultCacheStoragePolicy{
	return ASICacheForSessionDurationCacheStoragePolicy;
}

- (void)doRequest:(ASIHTTPRequest*)request 
          withTag:(NSString*)tag 
      andDelegate:(id<DataFetchingHandler>)delegat{
    
	[request setShouldAttemptPersistentConnection:NO];
	[request setDelegate:self];
	[request setUserInfo:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:tag,delegat,nil]
													 forKeys:[NSArray arrayWithObjects:kASIHTTPRequestTag,kASIHTTPResponseHanderDelegate,nil]]];
	[request setTimeOutSeconds:TIMEOUT];	
    
    [[FinAppsNetwork sharedInstance] addRequest:request];    
}

- (void)makePostRequest:(NSString*)urlStr
           withPOSTData:(NSData*)data
                    tag:(NSString*)tag 
            andDelegate:(id<DataFetchingHandler>)delegat{    
    
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlStr]];
	[request appendPostData:data];
	[request setRequestMethod:@"POST"];
    
	NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"application/json",@"application/json",nil]
																			 forKeys:[NSArray arrayWithObjects:@"Content-Type",@"Accept",nil]];
    
	[request setRequestHeaders:requestHeaders];
	
	[self doRequest:request withTag:tag andDelegate:delegat];
    
}

- (void)makeGetRequest:(NSString*)urlStr
			   withTag:(NSString*)tag
		   andDelegate:(id<DataFetchingHandler>)delegat{	
	
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlStr]];
	
	[self doRequest:request withTag:tag andDelegate:delegat];
}

#pragma mark ASIHTTPRequest Delegates

- (void)requestFinished:(ASIHTTPRequest *)request{
    
    if (kJSONFAKES) {
        [self requestFailed:request];
    } else {
        NSString *tag = [request.userInfo objectForKey:kASIHTTPRequestTag];	
        id <DataFetchingHandler> delegat = [request.userInfo objectForKey:kASIHTTPResponseHanderDelegate];
        int status = [request responseStatusCode];
        NSLog(@"Status code: %d for tag: %@",status,tag);
        NSString *dataResponseString = [request responseString];	// Use when fetching text data
        
        //JSON request asumed
        id parsedData = [self parseStr:dataResponseString];	
        
        if (parsedData != nil){
            if (delegat != nil && [(NSObject*)delegat respondsToSelector:@selector(dataFetchingCompleteWithTag:data:andStatus:)]) {
                [delegat dataFetchingCompleteWithTag:tag data:parsedData andStatus:status];
            }
        }
        else{
            DLog(@"Warning: Operación no controlada.");
            NSError *error = [request error];		
            [delegat dataFetchingDidFailWithTag:tag andError:error];
        }
    }
}

- (void)requestFailed:(ASIHTTPRequest *)request{    
    
    NSString *tag = [request.userInfo objectForKey:kASIHTTPRequestTag];
	id <DataFetchingHandler> delegat = [request.userInfo objectForKey:kASIHTTPResponseHanderDelegate];
	int status = [request responseStatusCode];
	DLog(@"Status code: %d",status);
    
    
    if (kJSONFAKES) {
        
        NSArray *keys = [NSArray arrayWithObjects:kNEARMETAG,kSEARCHHOUSESTAG, kDETAILTAG, kTRACKINGTAG, nil];
        
        NSArray *objects = [NSArray arrayWithObjects:@"apropmeu",@"cercaFiltres", @"detall", @"tracking", nil];
        
        NSDictionary *jsonDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
        
        NSError *errorJSON = nil;
        
        NSString *jsonString = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[jsonDict objectForKey:tag] ofType:@"json"]
                                                               encoding:NSUTF8StringEncoding
                                                                  error:&errorJSON];
        
        
        id parsedData = [self parseStr:jsonString];	
        [jsonString release];
        if (parsedData != nil){
            if (delegat != nil && [(NSObject*)delegat respondsToSelector:@selector(dataFetchingCompleteWithTag:data:andStatus:)]) {
                [delegat dataFetchingCompleteWithTag:tag data:parsedData andStatus:200];
            }
        }
        else{
            DLog(@"Warning: Operación no controlada.");
            NSError *error = [request error];		
            [delegat dataFetchingDidFailWithTag:tag andError:error]; 
        }
        
    }
    else {
        NSError *error = [request error];
        
        [delegat dataFetchingDidFailWithTag:tag andError:error];
    }
}


#pragma mark Data formatters

- (id)parseStr:(NSString *)str
{
	SBJsonParser *parser = [SBJsonParser new];
	id result = [parser objectWithString:str];
	[parser release];
	
	return result;
}

#pragma mark -
#pragma mark Singleton

static RestConsumer *sharedRESTCDelegate = nil;

// See "Creating a Singleton Instance" in the Cocoa Fundamentals Guide for more info
// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html

+ (RestConsumer *)sharedInstance {
	@synchronized(self) {
		if (sharedRESTCDelegate == nil) {
			sharedRESTCDelegate = [[self alloc] init]; // assignment not done here
		}
	}
	return sharedRESTCDelegate;
}

+ (id)allocWithZone:(NSZone *)zone {
	@synchronized(self) {
		if (sharedRESTCDelegate == nil) {
			sharedRESTCDelegate = [super allocWithZone:zone];
			return sharedRESTCDelegate;  // assignment and return on first allocation
		}
	}
	return nil; // on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone {
	return self;
}

- (id)retain {
	return self;
}

- (unsigned)retainCount {
	return UINT_MAX;  // denotes an object that cannot be released
}

- (oneway void)release {
	//do nothing
}

- (id)autorelease {
	return self;
}

@end
